package 练习;

import 抽象数据类型.ListNode;
import 抽象数据类型.Node;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * Copyright (C) 2023 思创数码科技股份有限公司
 * <p/>
 * 版权所有
 * <p/>
 * 类名　　  : Lru实现
 * 功能概要  :
 *
 * @Author : yangwk
 * @Date : 2024/3/17 17:39
 */
public class Lru实现 {
    public static void main(String[] args) {
        LRUCache lruCache = new LRUCache(2);
        lruCache.put(1, 1);
        lruCache.put(2, 2);
        lruCache.get(1);
        lruCache.put(3, 3);
        lruCache.get(2);

    }

    static class LRUCache {
        class DoubleNode {
            private int val;
            private DoubleNode pre;
            private DoubleNode next;
            private int key;

            public int getKey() {
                return key;
            }

            public void setKey(int key) {
                this.key = key;
            }

            public DoubleNode(int key, int val) {
                this.key = key;
                this.val = val;
            }

            public int getVal() {
                return val;
            }

            public void setVal(int val) {
                this.val = val;
            }

            public DoubleNode getPre() {
                return pre;
            }

            public void setPre(DoubleNode pre) {
                this.pre = pre;
            }

            public DoubleNode getNext() {
                return next;
            }

            public void setNext(DoubleNode next) {
                this.next = next;
            }
        }


        private Map<Integer, DoubleNode> map;
        private DoubleNode head;
        private DoubleNode tail;
        private int size = 0;

        public LRUCache(int capacity) {
            map = new HashMap<>(capacity);
            this.size = capacity;
        }

        public void moveToHead(DoubleNode node) {
            if (tail == null) {
                tail = node;
            }
            if (head == null) {
                head = node;
            }
            if (head == node) {
                return;
            }
            DoubleNode pre = node.getPre();
            DoubleNode next = node.getNext();
            node.next = head;
            node.pre = null;
            head.pre = node;
            if (pre != null) {
                pre.next = next;
            }
            if (next != null) {
                next.pre = pre;
            }
            head = node;
            if (tail == node) {
                tail = pre;
            }
        }

        public int get(int key) {
            if (map.containsKey(key)) {
                DoubleNode doubleNode = map.get(key);
                moveToHead(doubleNode);
                return doubleNode.val;
            }
            return -1;
        }

        public int size() {
            return this.map.size();
        }

        public void put(int key, int value) {
            if (map.containsKey(key)) {
                DoubleNode doubleNode = map.get(key);
                doubleNode.setVal(value);
                moveToHead(doubleNode);
            } else {
                if (size() >= size) {
                    int key1 = tail.getKey();
                    map.remove(key1);
                    removeOld();
                }
                DoubleNode doubleNode = new DoubleNode(key, value);
                map.put(key, doubleNode);
                moveToHead(doubleNode);
            }
        }

        public void removeOld() {
            if (tail != null) {
                if (head == tail) {
                    head = tail = null;
                } else {
                    DoubleNode pre = tail.getPre();
                    if (pre != null) {
                        pre.setNext(null);
                        tail = pre;
                    }
                }
            }
        }

    }

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */
}
